package com.ls.demo.tcp.protocol;

import com.ls.demo.tcp.namespace.Namespaces;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import io.netty.util.AttributeKey;
import lombok.extern.java.Log;

import java.util.List;
import java.util.UUID;

/**
 * 二进制字节转为16进制
 * @author liShan
 * @date 2019/8/30 12:59
 */
@Log
public class ByteToHexDecoder extends ByteToMessageDecoder {

    private final Namespaces namespaces = Namespaces.getInstance();

    @Override
    public void channelActive(ChannelHandlerContext ctx){
        UUID uuid = UUID.randomUUID();
        AttributeKey<UUID> id = AttributeKey.valueOf("id");
        AttributeKey<Boolean> identity = AttributeKey.valueOf("identity");
        ctx.channel().attr(id).setIfAbsent(uuid);
        ctx.channel().attr(identity).setIfAbsent(false);
        namespaces.setClient(uuid, ctx);
        log.info(String.format("连接建立了,现有连接个数%s", namespaces.size()));
    }

    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) {
        if (this.judgeHttp(in)) {
            ctx.channel().close();
            return;
        }
        StringBuilder stringBuilder = new StringBuilder();
        String temp;
        for (int i = 0; i < in.readableBytes(); i++) {
            temp = Integer.toHexString(in.getByte(i) & 0xFF);
            if (temp.length()==1){
                //1得到一位的进行补0操作
                stringBuilder.append("0");
            }
            stringBuilder.append(temp.toUpperCase()).append(" ");
        }
        out.add(stringBuilder);
        in.skipBytes(in.readableBytes());
    }

    /**
     * 判断是否是http请求
     * @param in 输入
     * @return 判断结果
     */
    private boolean judgeHttp(ByteBuf in){
        // http握手的协议前缀
        String[] httpPrefixs = new String[]{"GET /", "POST /", "HEAD /",
                "OPTIONS /", "PUT /", "DELETE /", "TRACE /", "CONNECT /", "PATCH /"};
        String protocol = getBufStart(in);
        for (String str : httpPrefixs) {
            if (protocol.startsWith(str)) {
                return true;
            }
        }
        return false;
    }

    private String getBufStart(ByteBuf in){
        // 默认暗号长度为23
        int maxLength = 23;
        int length = in.readableBytes();
        if (length > maxLength) {
            length = maxLength;
        }
        // 标记读位置
        in.markReaderIndex();
        byte[] content = new byte[length];
        in.readBytes(content);
        in.resetReaderIndex();
        return new String(content);
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) {
        ctx.writeAndFlush(Unpooled.EMPTY_BUFFER);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        cause.printStackTrace();
        ctx.close();
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx){
        AttributeKey<UUID> id = AttributeKey.valueOf("id");
        UUID uuid = ctx.channel().attr(id).get();
        namespaces.removeClient(uuid);
        log.info(String.format("连接断开了,现有连接个数%s", namespaces.size()));
    }

}
